/*
 * Modify by : line 27、33、341，Add line 326—333(Add clear function to datafield)
 * Modify by : line 365，Sometimes the datemenu displayed at top-left in IE, fix
 * it. Modify by : line 121，Add clear event
 * 
 * 
 * Ext JS Library 2.2
 * 
 * 
 * Copyright(c) 2006-2008, Ext JS, LLC.
 * 
 * 
 * [email]licensing@extjs.com[/email]
 * 
 * 
 * 
 * 
 * 
 * [url]http://extjs.com/license[/url]
 * 
 * 
 */

/**
 * @class Ext.ux.DateField
 * @extends Ext.form.TriggerField Provides a date input field with a
 *          {@link Ext.DatePicker} dropdown and automatic date validation.
 * @constructor Create a new DateField
 * @param {Object}
 *            config
 */
Ext.ux.DateField = Ext
		.extend(
				Ext.form.TwinTriggerField,
				{
					/**
					 * @cfg {String} format The default date format string which
					 *      can be overriden for localization support. The
					 *      format must be valid according to
					 *      {@link DateparseDate} (defaults to 'm/d/Y').
					 */
					format : "Y-m-d",
					readOnly : true, /* format: "m/d/Y", */
					/**
					 * @cfg {String} altFormats Multiple date formats separated
					 *      by "|" to try when parsing a user input value and it
					 *      doesn't match the defined format (defaults to
					 *      'm/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d').
					 */
					altFormats : "m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d",
					/**
					 * @cfg {String} disabledDaysText The tooltip to display
					 *      when the date falls on a disabled day (defaults to
					 *      'Disabled')
					 */
					disabledDaysText : "Disabled",
					/**
					 * @cfg {String} disabledDatesText The tooltip text to
					 *      display when the date falls on a disabled date
					 *      (defaults to 'Disabled')
					 */
					disabledDatesText : "Disabled",
					/**
					 * @cfg {String} minText The error text to display when the
					 *      date in the cell is before minValue (defaults to
					 *      'The date in this field must be after {minValue}').
					 */
					minText : "The date in this field must be equal to or after {0}",
					/**
					 * @cfg {String} maxText The error text to display when the
					 *      date in the cell is after maxValue (defaults to 'The
					 *      date in this field must be before {maxValue}').
					 */
					maxText : "The date in this field must be equal to or before {0}",
					/**
					 * @cfg {String} invalidText The error text to display when
					 *      the date in the field is invalid (defaults to
					 *      '{value} is not a valid date - it must be in the
					 *      format {format}').
					 */
					invalidText : "{0} is not a valid date - it must be in the format {1}",
					/**
					 * @cfg {String} triggerClass An additional CSS class used
					 *      to style the trigger button. The trigger will always
					 *      get the class 'x-form-trigger' and triggerClass will
					 *      be <b>appended</b> if specified (defaults to
					 *      'x-form-date-trigger' which displays a calendar
					 *      icon).
					 */
					triggerClass : 'x-form-date-trigger',
					/**
					 * @cfg {Boolean} showToday False to hide the footer area of
					 *      the DatePicker containing the Today button and
					 *      disable the keyboard handler for spacebar that
					 *      selects the current date (defaults to true).
					 */
					showToday : true,
					/**
					 * @cfg {Date/String} minValue The minimum allowed date. Can
					 *      be either a Javascript date object or a string date
					 *      in a valid format (defaults to null).
					 */
					/**
					 * @cfg {Date/String} maxValue The maximum allowed date. Can
					 *      be either a Javascript date object or a string date
					 *      in a valid format (defaults to null).
					 */
					/**
					 * @cfg {Array} disabledDays An array of days to disable, 0
					 *      based. For example, [0, 6] disables Sunday and
					 *      Saturday (defaults to null).
					 */
					/**
					 * @cfg {Array} disabledDates An array of "dates" to
					 *      disable, as strings. These strings will be used to
					 *      build a dynamic regular expression so they are very
					 *      powerful. Some examples:
					 *      <ul>
					 *      <li>["03/08/2003", "09/16/2003"] would disable
					 *      those exact dates</li>
					 *      <li>["03/08", "09/16"] would disable those days for
					 *      every year</li>
					 *      <li>["^03/08"] would only match the beginning
					 *      (useful if you are using short years)</li>
					 *      <li>["03/../2006"] would disable every day in March
					 *      2006</li>
					 *      <li>["^03"] would disable every day in every March</li>
					 *      </ul>
					 *      Note that the format of the dates included in the
					 *      array should exactly match the {@link format}
					 *      config. In order to support regular expressions, if
					 *      you are using a date format that has "." in it, you
					 *      will have to escape the dot when restricting dates.
					 *      For example: ["03\\.08\\.03"].
					 */
					/**
					 * @cfg {String/Object} autoCreate A DomHelper element spec,
					 *      or true for a default element spec (defaults to
					 *      {tag: "input", type: "text", size: "10",
					 *      autocomplete: "off"})
					 */

					// private
					defaultAutoCreate : {
						tag : "input",
						type : "text",
						size : "10",
						autocomplete : "off"
					},

					hideTrigger1 : true,
					initComponent : function() {
						Ext.ux.DateField.superclass.initComponent.call(this);

						this.addEvents("clear");

						if (typeof this.minValue == "string") {
							this.minValue = this.parseDate(this.minValue);
						}
						if (typeof this.maxValue == "string") {
							this.maxValue = this.parseDate(this.maxValue);
						}
						this.ddMatch = null;
						this.initDisabledDays();
					},

					// private
					initDisabledDays : function() {
						if (this.disabledDates) {
							var dd = this.disabledDates;
							var re = "(?:";
							for (var i = 0;i < dd.length; i++) {
								re += dd[i];
								if (i != dd.length - 1)
									re += "|";
							}
							this.disabledDatesRE = new RegExp(re + ")");
						}
					},

					/**
					 * Replaces any existing disabled dates with new values and
					 * refreshes the DatePicker.
					 * 
					 * @param {Array}
					 *            disabledDates An array of date strings (see
					 *            the {@link disabledDates} config for details
					 *            on supported values) used to disable a pattern
					 *            of dates.
					 */
					setDisabledDates : function(dd) {
						this.disabledDates = dd;
						this.initDisabledDays();
						if (this.menu) {
							this.menu.picker
									.setDisabledDates(this.disabledDatesRE);
						}
					},

					/**
					 * Replaces any existing disabled days (by index, 0-6) with
					 * new values and refreshes the DatePicker.
					 * 
					 * @param {Array}
					 *            disabledDays An array of disabled day indexes.
					 *            See the {@link disabledDays} config for
					 *            details on supported values.
					 */
					setDisabledDays : function(dd) {
						this.disabledDays = dd;
						if (this.menu) {
							this.menu.picker.setDisabledDays(dd);
						}
					},

					/**
					 * Replaces any existing {@link minValue} with the new value
					 * and refreshes the DatePicker.
					 * 
					 * @param {Date}
					 *            value The minimum date that can be selected
					 */
					setMinValue : function(dt) {
						this.minValue = (typeof dt == "string" ? this
								.parseDate(dt) : dt);
						if (this.menu) {
							this.menu.picker.setMinDate(this.minValue);
						}
					},

					/**
					 * Replaces any existing {@link maxValue} with the new value
					 * and refreshes the DatePicker.
					 * 
					 * @param {Date}
					 *            value The maximum date that can be selected
					 */
					setMaxValue : function(dt) {
						this.maxValue = (typeof dt == "string" ? this
								.parseDate(dt) : dt);
						if (this.menu) {
							this.menu.picker.setMaxDate(this.maxValue);
						}
					},

					// private
					validateValue : function(value) {
						value = this.formatDate(value);
						if (!Ext.ux.DateField.superclass.validateValue.call(
								this, value)) {
							return false;
						}
						if (value.length < 1) { // if it's blank and textfield
												// didn't flag it then it's
												// valid
							return true;
						}
						var svalue = value;
						value = this.parseDate(value);
						if (!value) {
							this.markInvalid(String.format(this.invalidText,
									svalue, this.format));
							return false;
						}
						var time = value.getTime();
						if (this.minValue && time < this.minValue.getTime()) {
							this.markInvalid(String.format(this.minText, this
									.formatDate(this.minValue)));
							return false;
						}
						if (this.maxValue && time > this.maxValue.getTime()) {
							this.markInvalid(String.format(this.maxText, this
									.formatDate(this.maxValue)));
							return false;
						}
						if (this.disabledDays) {
							var day = value.getDay();
							for (var i = 0;i < this.disabledDays.length; i++) {
								if (day === this.disabledDays[i]) {
									this.markInvalid(this.disabledDaysText);
									return false;
								}
							}
						}
						var fvalue = this.formatDate(value);
						if (this.ddMatch && this.ddMatch.test(fvalue)) {
							this.markInvalid(String.format(
									this.disabledDatesText, fvalue));
							return false;
						}
						return true;
					},

					// private
					// Provides logic to override the default
					// TriggerField.validateBlur which just returns true
					validateBlur : function() {
						return !this.menu || !this.menu.isVisible();
					},

					/**
					 * Returns the current date value of the date field.
					 * 
					 * @return {Date} The date value
					 */
					getValue : function() {
						return this
								.parseDate(Ext.ux.DateField.superclass.getValue
										.call(this))
								|| "";
					},

					/**
					 * Sets the value of the date field. You can pass a date
					 * object or any string that can be parsed into a valid
					 * date, using DateField.format as the date format,
					 * according to the same rules as {@link DateparseDate} (the
					 * default format used is "m/d/Y"). <br />
					 * Usage:
					 * 
					 * <pre><code>
					 * //All of these calls set the same date value (May 4, 2006)
					 * 
					 * //Pass a date object:
					 * var dt = new Date('5/4/2006');
					 * dateField.setValue(dt);
					 * 
					 * //Pass a date string (default format):
					 * dateField.setValue('05/04/2006');
					 * 
					 * //Pass a date string (custom format):
					 * dateField.format = 'Y-m-d';
					 * dateField.setValue('2006-05-04');
					 * </code></pre>
					 * 
					 * @param {String/Date}
					 *            date The date or valid date string
					 */
					setValue : function(date) {
						Ext.ux.DateField.superclass.setValue.call(this, this
								.formatDate(this.parseDate(date)));
						this.triggers[0].show();
					},

					// private
					parseDate : function(value) {
						if (!value || Ext.isDate(value)) {
							return value;
						}
						var v = Date.parseDate(value, this.format);
						if (!v && this.altFormats) {
							if (!this.altFormatsArray) {
								this.altFormatsArray = this.altFormats
										.split("|");
							}
							for (var i = 0, len = this.altFormatsArray.length;i < len
									&& !v; i++) {
								v = Date.parseDate(value,
										this.altFormatsArray[i]);
							}
						}
						return v;
					},

					// private
					onDestroy : function() {
						if (this.menu) {
							this.menu.destroy();
						}
						if (this.wrap) {
							this.wrap.remove();
						}
						Ext.ux.DateField.superclass.onDestroy.call(this);
					},

					// private
					formatDate : function(date) {
						return Ext.isDate(date)
								? date.dateFormat(this.format)
								: date;
					},

					// private
					menuListeners : {
						select : function(m, d) {
							this.setValue(d);
						},
						show : function() { // retain focus styling
							this.onFocus();
						},
						hide : function() {
							this.focus.defer(10, this);
							var ml = this.menuListeners;
							this.menu.un("select", ml.select, this);
							this.menu.un("show", ml.show, this);
							this.menu.un("hide", ml.hide, this);
						}
					},

					trigger1Class : 'x-form-clear-trigger',
					trigger2Class : 'x-form-date-trigger',
					onTrigger1Click : function() {
						if (this.disabled) {
							return;
						}

						this.setValue(null);
						this.fireEvent("clear", this);
						this.triggers[0].hide();
					},

					/**
					 * @method onTriggerClick
					 * @hide
					 */
					// private
					// Implements the default empty TriggerField.onTriggerClick
					// function to display the DatePicker
					onTrigger2Click : function() {
						if (this.disabled) {
							return;
						}
						if (this.menu == null) {
							this.menu = new Ext.menu.DateMenu();
						}
						Ext.apply(this.menu.picker, {
							minDate : this.minValue,
							maxDate : this.maxValue,
							disabledDatesRE : this.ddMatch,
							disabledDatesText : this.disabledDatesText,
							disabledDays : this.disabledDays,
							disabledDaysText : this.disabledDaysText,
							format : this.format,
							showToday : this.showToday,
							minText : String.format(this.minText, this
									.formatDate(this.minValue)),
							maxText : String.format(this.maxText, this
									.formatDate(this.maxValue))
						});
						this.menu.on(Ext.apply( {}, this.menuListeners, {
							scope : this
						}));
						this.menu.picker
								.setValue(this.getValue() || new Date());
						// this.menu.show(this.el, "tl-bl?");
						this.menu.show(this.wrap, "tl-bl?");
					},

					// private
					beforeBlur : function() {
						var v = this.parseDate(this.getRawValue());
						if (v) {
							this.setValue(v);
						}
					}

				/**
				 * @cfg {Boolean} grow
				 * @hide
				 */
				/**
				 * @cfg {Number} growMin
				 * @hide
				 */
				/**
				 * @cfg {Number} growMax
				 * @hide
				 */
				/**
				 * @hide
				 * @method autoSize
				 */
				});
Ext.reg('datefield', Ext.ux.DateField);